package cn.chench.util;

import java.beans.Transient;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class AnnotationUtil{
	
	
	/**
	 * 获取class
	 *@author chencaihui 
	 *@datetime 创建时间：2017年8月26日 下午12:17:04 
	 * @param classUrl
	 * @return
	 */
	public static Class<?> getClass(String classUrl) {
		if(NullUtil.isNotNull(classUrl)){
			try {
				return Class.forName(classUrl);
			} catch (ClassNotFoundException e) {}
		}
		return null;
	}
	
	/**
	 * 实例化对象
	 *@author chencaihui 
	 *@datetime 创建时间：2017年3月18日 下午12:09:17 
	 * @param classUrl 类路径
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T instance(String classUrl) {
		try {
			return (T)getClass(classUrl).newInstance();
		} catch (Exception e) {
			return null;
		}
	}
	
	/**
	 * 查找字段中的注解
	 *@author chencaihui 
	 *@datetime 创建时间：2017年3月18日 下午12:20:46 
	 * @param classes
	 * @param annClass
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static boolean existsFieldAnnotation(Class<?> classes, Class annClass) {
		List<Field> fieldList = getAllFields(classes);
		if (NullUtil.isNotNull(fieldList)) {
			for (Field field : fieldList) {
				Object object = field.getAnnotation(annClass);
				if(object!=null){
					return true;
				}
			}
		}
		return false;
	}
	
	/**
	 * 查找字段中的注解
	 *@author chencaihui 
	 *@datetime 创建时间：2017年3月18日 下午12:20:46 
	 * @param classes
	 * @param annClass
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static boolean existsFieldAnnotation(Class<?> classes, String fieldName, Class annClass) {
		List<Field> fieldList = getAllFields(classes);
		if (NullUtil.isNotNull(fieldList)) {
			for (Field field : fieldList) {
				if(fieldName.equals(field.getName())){
					Object object = field.getAnnotation(annClass);
					if(object!=null){
						return true;
					}
					break;
				}
			}
		}
		return false;
	}
	
	/**
	 * 查找方法中的注解
	 *@author chencaihui 
	 *@datetime 创建时间：2017年3月18日 下午12:20:46 
	 * @param classes
	 * @param annClass
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static boolean existsMethodAnnotation(Class<?> classes, Class annClass) {
		List<Method> methodList = getAllMethods(classes);
		if (NullUtil.isNotNull(methodList)) {
			for (Method Method : methodList) {
				Object object = Method.getAnnotation(annClass);
				if(object!=null){
					return true;
				}
			}
		}
		return false;
	}
	
	/**
	 * 查找方法中的注解
	 *@author chencaihui 
	 *@datetime 创建时间：2017年3月18日 下午12:20:46 
	 * @param classes
	 * @param annClass
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static boolean existsMethodAnnotation(Class<?> classes, String methodName, Class annClass) {
		List<Method> methodList = getAllMethods(classes);
		if (NullUtil.isNotNull(methodList)) {
			for (Method method : methodList) {
				if(methodName.equals(method.getName())){
					Object object = method.getAnnotation(annClass);
					if(object!=null){
						return true;
					}
					break;
				}
			}
		}
		return false;
	}

	/**
	 * 获取字段的所有注解
	 *@author chencaihui 
	 *@datetime 创建时间：2017年3月18日 下午12:24:18 
	 * @param classes
	 * @return
	 */
	public static Map<String, Annotation> getFieldAnnotations(Class<?> classes) {
		List<Field> fieldList = getAllFields(classes);
		if (NullUtil.isNotNull(fieldList)) {
			Map<String, Annotation> annotationMap = new LinkedHashMap<String, Annotation>();
			for (Field field : fieldList) {
				Annotation[] annotations = field.getAnnotations();
				for (int i = 0; i < annotations.length; i++) {
					annotationMap.put(field.getName(), annotations[i]);
				}
			}
			return annotationMap;
		}
		return null;
	}
	
	/**
	 * 获取方法的所有注解
	 *@author chencaihui 
	 *@datetime 创建时间：2017年3月18日 下午12:24:18 
	 * @param classes
	 * @return
	 */
	public static Map<String, Annotation> getMethodAnnotations(Class<?> classes) {
		List<Method> methodList = getAllMethods(classes);
		if (NullUtil.isNotNull(methodList)) {
			Map<String, Annotation> annotationMap = new LinkedHashMap<String, Annotation>();
			for (Method method : methodList) {
				Annotation[] annotations = method.getAnnotations();
				for (int i = 0; i < annotations.length; i++) {
					annotationMap.put(method.getName(), annotations[i]);
				}
			}
			return annotationMap;
		}
		return null;
	}

	
	/**
	 * 获取当前类所有方法
	 *@author chencaihui 
	 *@datetime 创建时间：2017年3月18日 下午12:38:05 
	 * @param classes
	 * @return
	 */
	public static List<Method> getCurrentClassMethods(Class<?> classes) {
		List<Method> methodList = new ArrayList<Method>();
		Method[] methods = classes.getDeclaredMethods();
		if (NullUtil.isNotNull(methods)) {
			for (Method method : methods) {
				methodList.add(method);
			}
		}
		return methodList;
	}
	
	/**
	 * 获取当前类和父类所有方法
	 *@author chencaihui 
	 *@datetime 创建时间：2017年3月18日 下午12:38:13 
	 * @param classes
	 * @return
	 */
	public static List<Method> getAllMethods(Class<?> classes) {
		List<Method> methodList = new ArrayList<Method>();
		Method[] methods = classes.getDeclaredMethods();
		if (NullUtil.isNotNull(methods)) {
			for (Method method : methods) {
				methodList.add(method);
			}
		}
		if (classes != Object.class && classes.getSuperclass() != Object.class) {
			methods = classes.getSuperclass().getDeclaredMethods();
			if (NullUtil.isNotNull(methods)) {
				for (Method method : methods) {
					methodList.add(method);
				}
			}
		}
		return methodList;
	}
	
	
	/**
	 * 获取当前类所有字段
	 */
	public static List<Field> getCurrentClassFields(Class<?> classes) {
		List<Field> fieldList = new ArrayList<Field>();
		Field[] fields = classes.getDeclaredFields();
		if (NullUtil.isNotNull(fields)) {
			for (Field field : fields) {
				if(Modifier.isStatic(field.getModifiers())) {//跳过静态变量
		        	continue;
		        }
				fieldList.add(field);
			}
		}
		return fieldList;
	}
	
	/**
	 * 获取当前类所有字段（不包含Transient）
	 */
	public static List<Field> getCurrentClassFieldsNotTransient(Class<?> classes) {
		List<Field> fieldList = new ArrayList<Field>();
		Field[] fields = classes.getDeclaredFields();
		if (NullUtil.isNotNull(fields)) {
			for (Field field : fields) {
				if(Modifier.isStatic(field.getModifiers())) {//跳过静态变量
		        	continue;
		        }
				Transient ts = field.getAnnotation(Transient.class);
				if(NullUtil.isNotNull(ts))//过滤Transient
					continue;
				fieldList.add(field);
			}
		}
		return fieldList;
	}
	
	/**
	 * 获取当前类和父类所有字段（不包含Transient）
	 */
	public static List<Field> getAllFieldsNotTransient(Class<?> classes) {
		List<Field> fieldList = new ArrayList<Field>();
		Field[] fields = classes.getDeclaredFields();
		if (NullUtil.isNotNull(fields)) {
			for (Field field : fields) {
				if(Modifier.isStatic(field.getModifiers())) {//跳过静态变量
		        	continue;
		        }
				Transient ts = field.getAnnotation(Transient.class);
				if(NullUtil.isNotNull(ts))//过滤Transient
					continue;
				fieldList.add(field);
			}
		}
		if (classes != Object.class && classes.getSuperclass() != Object.class) {
			fields = classes.getSuperclass().getDeclaredFields();
			if (NullUtil.isNotNull(fields)) {
				for (Field field : fields) {
					if(Modifier.isStatic(field.getModifiers())) {//跳过静态变量
			        	continue;
			        }
					Transient ts = field.getAnnotation(Transient.class);
					if(NullUtil.isNotNull(ts))//过滤Transient
						continue;
					fieldList.add(field);
				}
			}
		}
		return fieldList;
	}
	
	/**
	 * 获取当前类和父类所有字段
	 */
	public static List<Field> getAllFields(Class<?> classes) {
		List<Field> fieldList = new ArrayList<Field>();
		if(classes!=null){
			Field[] fields = classes.getDeclaredFields();
			if (NullUtil.isNotNull(fields)) {
				for (Field field : fields) {
					if(Modifier.isStatic(field.getModifiers())) {//跳过静态变量
			        	continue;
			        }
					fieldList.add(field);
				}
			}
			if (classes != Object.class && classes.getSuperclass() != Object.class) {
				fields = classes.getSuperclass().getDeclaredFields();
				if (NullUtil.isNotNull(fields)) {
					for (Field field : fields) {
				        if(Modifier.isStatic(field.getModifiers())) {//跳过静态变量
				        	continue;
				        }
						fieldList.add(field);
					}
				}
			}
		}
		return fieldList;
	}
	
	
	/**
	 * 利用反射设置指定对象的指定属性为指定的值
	 * @param obj 目标对象
	 * @param fieldName 目标属性
	 * @param fieldValue 目标值
	 */
	public static void setFieldValue(Object obj, String fieldName, Object fieldValue) {
		try {
			Field field = getField(obj, fieldName);
			if (field != null) {
				setFieldValue(obj, field, fieldValue);
			}
		} catch (Exception e) {
			LoggerUtil.warn( "setFieldValue error["+obj.getClass().getSimpleName()+"."+fieldName+":"+fieldValue+"]:"+e.getMessage());
		}
	}
	
	public static void setFieldValue(Object obj, Field field, Object fieldValue) {
		try {
			if (field != null) {
				String type = field.getType().toString();
				field.setAccessible(true);
				if(type.endsWith("String")){
					if(NullUtil.isNull(fieldValue)) {
						field.set(obj, null);
					}else {
						field.set(obj, fieldValue.toString());
					}
				}else if(type.endsWith("long")){
					if(NullUtil.isNull(fieldValue)) {
						field.set(obj, 0L);
					}else {
						field.set(obj, Long.parseLong(String.valueOf(fieldValue)));
					}
				}else if(type.endsWith("Long")){
					if(NullUtil.isNull(fieldValue)) {
						field.set(obj, null);
					}else {
						field.set(obj, Long.parseLong(fieldValue.toString()));
					}
				}else if(type.endsWith("int")){
					if(NullUtil.isNull(fieldValue)) {
						field.set(obj, (int)0);
					}else {
						field.set(obj, Integer.parseInt(fieldValue.toString()));
					}
				}else if(type.endsWith("Integer")){  
					if(NullUtil.isNull(fieldValue)) {
						field.set(obj, null);
					}else {
						field.set(obj, Integer.parseInt(fieldValue.toString()));
					}
				}else if(type.endsWith("double")){
					if(NullUtil.isNull(fieldValue)) {
						field.set(obj, 0.0);
					}else {
						field.set(obj, Double.parseDouble(fieldValue.toString()));
					}
				}else if(type.endsWith("Double")){  
					if(NullUtil.isNull(fieldValue)) {
						field.set(obj, null);
					}else {
						field.set(obj, Double.parseDouble(fieldValue.toString()));
					}
				}else if(type.endsWith("BigDecimal")){
					if(NullUtil.isNull(fieldValue)) {
						field.set(obj, null);
					}else {
						field.set(obj, new BigDecimal(fieldValue.toString()));
					}
				}else if(type.endsWith("Date")){
					if(NullUtil.isNull(fieldValue)) {
						field.set(obj, null);
					}else {
						if(fieldValue instanceof Date) {
							field.set(obj, (Date)fieldValue);
						}else {
							Date date = DateUtils.isDate(String.valueOf(fieldValue));
							if(date!=null){
								field.set(obj, date);
							}else{
								field.set(obj, fieldValue);
							}
						}
					}
				}else{
					field.set(obj, fieldValue);
				}
			}
		} catch (Exception e) {
			LoggerUtil.warn( "setFieldValue error["+obj.getClass().getSimpleName()+"."+field.getName()+":"+fieldValue+"]:"+e.getMessage());
		}
	}
	
	/**
	 * 利用反射获取指定对象里面的指定属性
	 * @param obj 目标对象
	 * @param fieldName 目标属性
	 * @return 目标字段
	 */
	public static Field getField(Object obj, String fieldName) {
		Field field = null;
		for (Class<?> clazz = obj.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) {
			try {
				field = clazz.getDeclaredField(fieldName);
				break;
			} catch (NoSuchFieldException e) {}
		}
		return field;
	}
	
	/**
	 * 获取对象字段
	 *@author chencaihui 
	 *@datetime 创建时间：2018年3月15日 下午5:41:42 
	 * @param clazz
	 * @param fieldName
	 * @return
	 */
	public static Field getField(Class<?> clazz, String fieldName) {
		Field field = null;
		for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
			try {
				field = clazz.getDeclaredField(fieldName);
				break;
			} catch (NoSuchFieldException e) {}
		}
		return field;
	}
	
	/**
	 * 利用反射获取指定对象的指定属性
	 * @param obj 目标对象
	 * @param fieldName 目标属性
	 * @return 目标属性的值
	 */
	public static Object getFieldValue(Object obj, String fieldName) {
		Object result = null;
		Field field = getField(obj, fieldName);
		if (field != null) {
			field.setAccessible(true);
			try {
				result = field.get(obj);
			} catch (IllegalArgumentException e) {
				LoggerUtil.error("异常", e.getMessage());
			} catch (IllegalAccessException e) {
				LoggerUtil.error("异常", e.getMessage());
			}
		}
		return result;
	}
	
	/**
	 * 获取对象属性值
	 * @author chench
	 * @date 2020年5月1日
	 * @param @param obj
	 * @param @param field
	 * @param @return
	 * @return Object
	 */
	public static Object getFieldValue(Object obj, Field field) {
		Object result = null;
		if (field != null) {
			field.setAccessible(true);
			try {
				result = field.get(obj);
			} catch (IllegalArgumentException e) {
				LoggerUtil.error("异常", e.getMessage());
			} catch (IllegalAccessException e) {
				LoggerUtil.error("异常", e.getMessage());
			}
		}
		return result;
	}
	
	/** 
	     * 通过java反射，获得定义类时声明的基类(父类)的泛型参数的类型. 
	     * 如类声明：public UserDao extends HibernateDao &lt;com.mass.demo.User&gt; ...,�? 
	     * 调用本方法语句getSuperClassGenericType(UserDao.class,0)返回User.class. 
     * @param clazz - 子类Class 
     * @param index - 基类层级 
     * @return 基类(父类)的泛型参数的类型 
     */  
    public static Class<?> getSuperClassGenericType(final Class<?> clazz, final int index){  
        Type genericType = clazz.getGenericSuperclass();  
        if(!(genericType instanceof ParameterizedType)){  
            return Object.class;  
        }  
        Type[] params = ((ParameterizedType) genericType).getActualTypeArguments();  
        if(index>=params.length || index < 0){  
            LoggerUtil.warn("Index:"+index+",size of "+clazz.getSimpleName()+"'s Parameterize Type:"+params.length);  
            return Object.class;  
        }  
        if(!(params[index] instanceof Class)){  
            return Object.class;  
        }
        return (Class<?>)params[index];   
    }  
	
}